Speicherung einer Splitterkonfiguration

Ich arbeite immer noch viel mit Dynpros. Für mich und die meisten meiner Kunden ist das nach wie vor das Frontend, mit dem gearbeitet wird. Bei der GUI-Programmierung habe ich mir angewöhnt, einzelne Teile in separaten Controls zu programmieren. Das hat den Vorteil, dass diese Module austauschbar und einzeln testbar sind. Um mehrere Module unterzubekommen, bieten sich Splittercontainer an. Diese haben jedoch den Nachteil, dass die Konfiguration (Größe, Breite, Höhe) feste definiert werden muss. Verwendet man nur einen Splitter, dann kann man dessen Größe einfach auslesen, speichern und bei Bedarf wieder setzen. So kann sich der/die Anwender:in die Größe so einstellen, wie es für das aktuelle Setup aus Monitorauflösung, Skalierung und SAPGUI-Schriftgröße am besten passt.

Verwendet man jedoch mehrere Splitter, dann und befindet sich zudem noch in der Findungsphase wo sich die Aufteilung der Container noch ändert, dann ist ein gezieltes Auslesen und Setzen der Größenparameter doch sehr aufwendig.

Idee

Da ich nicht nur ein Freund von Controls bin, sondern auch von generischen Lösungen, war meine erste Idee, die aktuelle Konfiguration der Controls automatisch zu ermitteln. Die Routine dafür war auch schnell geschrieben:

https://github.com/tricktresor/splitter_configuration/blob/main/src/ztrcktrsr_splitter_config_01.prog.abap

Das Programm erzeugt einen einigermaßen komplexen Bildschirmaufbau mit Splittern und liest diesen aus.

Dynpro mit Splittercontainern

Die Ausgabe der Konfiguration sieht wie folgt aus:

Allerdings gibt es hier ein Problem: Ich habe keine Möglichkeit herauszufinden, wie die Container bzw. die Splitter inhaltlich einzuordnen sind. Wenn ich mich, wie beschrieben, noch in der Entwicklungsphase befinde, dann kommt eventuell mal ein Container dazu, ein Splitter verschwindet oder bekommt mehr oder weniger Controls. Dementsprechend würde sich das Wiederherstellen ungewollt ändern.

Man kann zwar jedem Control einen Namen mitgeben, allerdings funktioniert dieses Feature nicht so, wie ich es mir vorgestellt habe. Wenn man die Namen, die übrigens nur aus Großbuchstaben und ohne Space bestehen müssen, vergibt, dann müssen alle Container und Controls einen Namen bekommen. Ansonsten gibt es einen Kurzdump.

Vorgehen

die Lösung hierfür besteht darin, eine Ableitung des Splittercontainers zu erstellen und diesen zu verwenden. In der Ableitung kann man den Parameter NAME des CONSTRUCTORs in einem eigenen Attribut speichern. Die Methode GET_NAME ist bereits vorhanden und ich redefiniere diese.

CLASS zcl_gui_splitter DEFINITION INHERITING FROM cl_gui_splitter_container.
  PUBLIC SECTION.
    METHODS constructor
      IMPORTING
        link_dynnr              TYPE  sy-dynnr
        link_repid              TYPE  sy-repid
        shellstyle              TYPE  i
        left                    TYPE  i
        top                     TYPE  i
        width                   TYPE  i
        height                  TYPE  i
        metric                  TYPE  cntl_metric
        align                   TYPE  i
        parent                  TYPE REF TO cl_gui_container
        rows                    TYPE  i
        columns                 TYPE  i
        no_autodef_progid_dynnr TYPE  c
        name                    TYPE  string.
    METHODS get_name REDEFINITION.

  PRIVATE SECTION.
    DATA my_name TYPE string.

ENDCLASS.

CLASS zcl_gui_splitter IMPLEMENTATION.
  METHOD constructor.
    super->constructor(
      link_dynnr              = link_dynnr
      link_repid              = link_repid
      shellstyle              = shellstyle
      left                    = left
      top                     = top
      width                   = width
      height                  = height
      metric                  = metric
      align                   = align
      parent                  = parent
      rows                    = rows
      columns                 = columns
      no_autodef_progid_dynnr = no_autodef_progid_dynnr ).

    my_name = name.

  ENDMETHOD.

  METHOD get_name.
    name = my_name.
  ENDMETHOD.

ENDCLASS.

Merkwürdigerweise funktioniert diese Variante nur, wenn man die Klasse global anlegt. mit einer lokalen Vererbung erhalte ich zwar keinen Fehler, aber leider auch keine Splittercontainer.

Container mit Namen

Dadurch, dass ich dem Splittercontainer nun einen Namen mitgeben kann, kann ich diesen auch wieder auslesen. Die Funktion ist genau so, wie bisher auch, nur dass ich nun eben auch den Namen ermitteln und speichern kann.

https://github.com/tricktresor/splitter_configuration/blob/main/src/ztrcktrsr_splitter_config_02.prog.abap

Die Konfiguration enthält nun alle Splitter mit Namen und deren Containergrößen

Splitter mit Namen

Lösung

Die aktuelle Konfiguration kann nun mit Namen ausgelesen werden. Dementsprechend kann ich die Konfiguration auch speichern. Ich habe es mir hier einfach gemacht und speichere sie per EXPORT TO DATABASE in INDX(Z2).

Beim Auslesen muss ich zusätzlich die aktuelle Konfiguration ermitteln, um mithilfe der Namen den aktiven Splitter zuordnen zu können. Zu diesem setze ich dann mit SET_ROW_HEIGHT die Höhe und mit SET_COLUMN_WIDHT die Breite der Splittercontainer.

Hier die endgültige Lösung:

https://github.com/tricktresor/splitter_configuration/blob/main/src/ztrcktrsr_splitter_config_03.prog.abap

Enno Wulff